use rustcloud_registry::{HealthCheckManager, HealthCheckResult};
use rustcloud_core::{ServiceInstance, HealthCheck, HealthCheckType};
use std::time::Duration;
use std::sync::Arc;

/// 示例：如何使用健康检查管理器
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化日志
    tracing_subscriber::init();
    
    // 创建健康检查管理器
    let health_manager = HealthCheckManager::new();
    
    // 创建服务实例
    let instance = ServiceInstance::new("user-service", "127.0.0.1", 8080, "http");
    
    // HTTP健康检查配置
    let http_health_check = HealthCheck {
        check_type: HealthCheckType::Http {
            path: "/health".to_string(),
            method: "GET".to_string(),
        },
        endpoint: "http://127.0.0.1:8080/health".to_string(),
        interval: Duration::from_secs(30),
        timeout: Duration::from_secs(5),
        failure_threshold: 3,
        success_threshold: 2,
    };
    
    // TCP健康检查配置
    let tcp_health_check = HealthCheck {
        check_type: HealthCheckType::Tcp,
        endpoint: "127.0.0.1:8080".to_string(),
        interval: Duration::from_secs(15),
        timeout: Duration::from_secs(3),
        failure_threshold: 3,
        success_threshold: 2,
    };
    
    // 脚本健康检查配置
    let script_health_check = HealthCheck {
        check_type: HealthCheckType::Script {
            command: "curl -f http://{host}:{port}/health".to_string(),
        },
        endpoint: "".to_string(),
        interval: Duration::from_secs(60),
        timeout: Duration::from_secs(10),
        failure_threshold: 2,
        success_threshold: 1,
    };
    
    // 定义状态变化回调
    let status_change_callback = Box::new(|instance: ServiceInstance, is_healthy: bool| {
        if is_healthy {
            println!("✅ 服务实例 {} 恢复健康", instance);
        } else {
            println!("❌ 服务实例 {} 变为不健康", instance);
        }
    });
    
    // 启动HTTP健康检查
    health_manager
        .start_health_check(
            instance.clone(),
            http_health_check,
            Some(status_change_callback),
        )
        .await?;
    
    println!("🚀 健康检查已启动，按 Ctrl+C 退出");
    
    // 等待用户中断
    tokio::signal::ctrl_c().await?;
    
    println!("🛑 正在停止健康检查...");
    
    // 停止健康检查
    health_manager.stop_health_check(&instance).await;
    
    // 获取最终健康状态
    if let Some(state) = health_manager.get_health_state(&instance).await {
        println!("📊 最终健康状态:");
        println!("  - 是否健康: {}", state.is_healthy);
        println!("  - 总检查次数: {}", state.total_checks);
        println!("  - 总失败次数: {}", state.total_failures);
        println!("  - 连续成功次数: {}", state.consecutive_successes);
        println!("  - 连续失败次数: {}", state.consecutive_failures);
    }
    
    println!("👋 健康检查示例结束");
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use tokio::time::{sleep, Duration};
    
    #[tokio::test]
    async fn test_http_health_check() {
        let health_manager = HealthCheckManager::new();
        let instance = ServiceInstance::new("test-service", "httpbin.org", 80, "http");
        
        let health_check = HealthCheck {
            check_type: HealthCheckType::Http {
                path: "/status/200".to_string(),
                method: "GET".to_string(),
            },
            endpoint: "http://httpbin.org/status/200".to_string(),
            interval: Duration::from_secs(1),
            timeout: Duration::from_secs(5),
            failure_threshold: 2,
            success_threshold: 1,
        };
        
        // 启动健康检查
        health_manager
            .start_health_check(instance.clone(), health_check, None)
            .await
            .unwrap();
        
        // 等待几次检查
        sleep(Duration::from_secs(3)).await;
        
        // 检查状态
        let state = health_manager.get_health_state(&instance).await;
        assert!(state.is_some());
        
        let state = state.unwrap();
        assert!(state.total_checks > 0);
        assert!(state.is_healthy);
        
        // 停止健康检查
        health_manager.stop_health_check(&instance).await;
    }
    
    #[tokio::test]
    async fn test_tcp_health_check() {
        let health_manager = HealthCheckManager::new();
        let instance = ServiceInstance::new("test-service", "8.8.8.8", 53, "tcp");
        
        let health_check = HealthCheck {
            check_type: HealthCheckType::Tcp,
            endpoint: "8.8.8.8:53".to_string(),
            interval: Duration::from_secs(1),
            timeout: Duration::from_secs(2),
            failure_threshold: 2,
            success_threshold: 1,
        };
        
        // 启动健康检查
        health_manager
            .start_health_check(instance.clone(), health_check, None)
            .await
            .unwrap();
        
        // 等待几次检查
        sleep(Duration::from_secs(3)).await;
        
        // 检查状态
        let state = health_manager.get_health_state(&instance).await;
        assert!(state.is_some());
        
        let state = state.unwrap();
        assert!(state.total_checks > 0);
        // DNS服务器应该是健康的
        assert!(state.is_healthy);
        
        // 停止健康检查
        health_manager.stop_health_check(&instance).await;
    }
    
    #[tokio::test]
    async fn test_script_health_check() {
        let health_manager = HealthCheckManager::new();
        let instance = ServiceInstance::new("test-service", "127.0.0.1", 8080, "http");
        
        let health_check = HealthCheck {
            check_type: HealthCheckType::Script {
                // 简单的脚本：检查端口是否可达
                command: if cfg!(target_os = "windows") {
                    "ping -n 1 {host}".to_string()
                } else {
                    "ping -c 1 {host}".to_string()
                },
            },
            endpoint: "".to_string(),
            interval: Duration::from_secs(2),
            timeout: Duration::from_secs(5),
            failure_threshold: 2,
            success_threshold: 1,
        };
        
        // 启动健康检查
        health_manager
            .start_health_check(instance.clone(), health_check, None)
            .await
            .unwrap();
        
        // 等待几次检查
        sleep(Duration::from_secs(5)).await;
        
        // 检查状态
        let state = health_manager.get_health_state(&instance).await;
        assert!(state.is_some());
        
        let state = state.unwrap();
        assert!(state.total_checks > 0);
        // localhost ping应该成功
        assert!(state.is_healthy);
        
        // 停止健康检查
        health_manager.stop_health_check(&instance).await;
    }
}